package cn.mengfly.product.hysitrix;

import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.hystrix.*;

/**
 * 主从模式
 *
 * @author Mengfly
 * @date 2021/3/13 16:32
 */
public class CommandFacadeWithPrimarySecondary extends HystrixCommand<String> {

    private final static DynamicBooleanProperty usePrimary =
            DynamicPropertyFactory.getInstance().getBooleanProperty("primarySecondary", true);

    private final int id;

    protected CommandFacadeWithPrimarySecondary(int id) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("SystemX"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("PrimarySecondaryCommand"))
                // 命令执行使用信号量隔离
                // 因为具体命令执行已经使用了线程池隔离方式
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)));
        this.id = id;
    }

    @Override
    protected String run() throws Exception {
        if (usePrimary.get()) {
            return new PrimaryCommand(id).execute();
        } else {
            // 主服务处理失败后执行从服务处理
            return new SecondaryCommand(id).execute();
        }
    }

    /**
     * 当主/从服务处理都不成功的时候返回一个静态数据
     */
    @Override
    protected String getFallback() {
        return "static-fallback-" + id;
    }

    /**
     * 主服务处理
     */
    private static class PrimaryCommand extends HystrixCommand<String> {
        private final int id;

        private PrimaryCommand(int id) {
            super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("SystemX"))
                    .andCommandKey(HystrixCommandKey.Factory.asKey("PrimaryCommand"))
                    .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("PrimaryCommand"))
                    // 主服务执行时间设置为600ms
                    .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(600)));
            this.id = id;
        }

        @Override
        protected String run() throws Exception {
            // 主服务的具体逻辑
            return "responseFromPrimary-" + id;
        }
    }


    /**
     * 从服务处理
     */
    private static class SecondaryCommand extends HystrixCommand<String> {
        private final int id;

        private SecondaryCommand(int id) {
            super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("SystemX"))
                    .andCommandKey(HystrixCommandKey.Factory.asKey("SecondaryCommand"))
                    .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("SecondaryCommand"))
                    // 主服务执行时间设置为100ms
                    .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100)));
            this.id = id;
        }

        @Override
        protected String run() throws Exception {
            // 主服务的具体逻辑
            return "responseFromSecondary-" + id;
        }
    }
}
